home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Term / Extras / Source / term-source.lha / Phone.c < prev    next >
C/C++ Source or Header  |  1996-10-20  |  13KB  |  640 lines

  1. /*
  2. **    Phone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16. PhoneEntry **
  17. CreatePhonebookTable(PhoneEntry **OldTable,LONG OldTableSize,LONG NumEntriesWanted,LONG *NumEntriesGot)
  18. {
  19.     PhoneEntry **Table;
  20.  
  21.         /* Don't allocate less than one entry */
  22.  
  23.     if(NumEntriesWanted < 1)
  24.         NumEntriesWanted = 1;
  25.  
  26.         /* Round to next multiple of eight */
  27.  
  28.     *NumEntriesGot = (NumEntriesWanted + 7) & ~7;
  29.  
  30.         /* Allocate the table */
  31.  
  32.     if(Table = (PhoneEntry **)AllocVecPooled(sizeof(PhoneEntry *) * (*NumEntriesGot),MEMF_ANY))
  33.     {
  34.         LONG From;
  35.  
  36.             /* If there is an old table given, copy it to the new table */
  37.  
  38.         if(OldTable)
  39.         {
  40.             CopyMem(OldTable,Table,sizeof(PhoneEntry *) * OldTableSize);
  41.  
  42.             From = OldTableSize;
  43.         }
  44.         else
  45.             From = 0;
  46.  
  47.             /* Clear all the unused entries */
  48.  
  49.         memset(&Table[From],0,(*NumEntriesGot - From) * sizeof(PhoneEntry *));
  50.     }
  51.  
  52.     return(Table);
  53. }
  54.  
  55. VOID
  56. DeletePhoneEntry(PhoneEntry *Entry)
  57. {
  58.     if(Entry)
  59.     {
  60.             /* Dispose of the dial node if any */
  61.  
  62.         if(Entry->DialNode)
  63.             DeleteDialNode(Entry->DialNode);
  64.  
  65.             /* Dispose of the phone node if any */
  66.  
  67.         if(Entry->Node)
  68.             FreeVecPooled(Entry->Node);
  69.  
  70.             /* Dispose of the configuration */
  71.  
  72.         if(Entry->Config)
  73.             DeleteConfiguration(Entry->Config);
  74.  
  75.             /* Get rid of the rates and costs */
  76.  
  77.         FreeTimeDateList((struct List *)&Entry->TimeDateList);
  78.  
  79.             /* Is this entry member of a group? */
  80.  
  81.         if(Entry->GroupNode)
  82.             FreeVecPooled(Entry->GroupNode);
  83.  
  84.         FreeVecPooled(Entry);
  85.     }
  86. }
  87.  
  88. PhoneEntry *
  89. CreatePhoneEntry(PhonebookHandle *PhoneHandle)
  90. {
  91.     PhoneEntry *NewEntry;
  92.  
  93.         /* Allocate space for the entry and the header data */
  94.  
  95.     if(NewEntry = (PhoneEntry *)AllocVecPooled(sizeof(PhoneEntry) + sizeof(PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  96.     {
  97.             /* Allocate space for the configuration data */
  98.  
  99.         if(NewEntry->Config = CreateConfiguration(FALSE))
  100.         {
  101.                 /* Put in the header and assign a unique ID to the entry */
  102.  
  103.             NewEntry->Header        = (PhoneHeader *)(NewEntry + 1);
  104.             NewEntry->Header->ID    = PhoneHandle->PhonebookID++;
  105.  
  106.                 /* Provide a default name */
  107.  
  108.             strcpy(NewEntry->Header->Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  109.  
  110.                 /* Initialize the creation time */
  111.  
  112.             GetSysTime(&NewEntry->Header->Creation);
  113.  
  114.                 /* Initialize the entry as `unmarked'. */
  115.  
  116.             NewEntry->Count = -1;
  117.  
  118.                 /* Initialize the dates and costs */
  119.  
  120.             NewList((struct List *)&NewEntry->TimeDateList);
  121.  
  122.                 /* Check if the phonebook has a display list attached */
  123.  
  124.             if(PhoneHandle->PhoneList)
  125.             {
  126.                     /* Create a display node */
  127.  
  128.                 if(!(NewEntry->Node = CreatePhoneNode(NewEntry,TRUE)))
  129.                 {
  130.                     FreeVecPooled(NewEntry);
  131.                     return(NULL);
  132.                 }
  133.             }
  134.  
  135.             return(NewEntry);
  136.         }
  137.  
  138.         FreeVecPooled(NewEntry);
  139.     }
  140.  
  141.     return(NULL);
  142. }
  143.  
  144. VOID
  145. RemovePhoneEntry(PhonebookHandle *PhoneHandle,PhoneEntry *Entry)
  146. {
  147.     PhoneEntry **Phonebook = PhoneHandle->Phonebook;
  148.     LONG i;
  149.  
  150.     for(i = 0 ; i < PhoneHandle->NumPhoneEntries ; i++)
  151.     {
  152.         if(Phonebook[i] == Entry)
  153.         {
  154.             LONG j;
  155.  
  156.                 /* Remove the entry from the table */
  157.  
  158.             for(j = i ; j < PhoneHandle->NumPhoneEntries ; j++)
  159.                 Phonebook[j] = Phonebook[j + 1];
  160.  
  161.                 /* Clear the last entry and shrink the phonebook */
  162.  
  163.             Phonebook[PhoneHandle->NumPhoneEntries--] = NULL;
  164.  
  165.                 /* Remove it from the dial list */
  166.  
  167.             RemoveDialNode(PhoneHandle,Entry->DialNode);
  168.  
  169.                 /* Remove it from the group list */
  170.  
  171.             RemoveGroupEntry(Entry);
  172.  
  173.                 /* Remove it from the display list */
  174.  
  175.             if(Entry->Node)
  176.                 Remove((struct Node *)Entry->Node);
  177.  
  178.             break;
  179.         }
  180.     }
  181. }
  182.  
  183. BOOL
  184. AddPhoneEntry(PhonebookHandle *PhoneHandle,PhoneEntry *NewEntry)
  185. {
  186.         /* If the phone book is filled `to the brim', expand it. */
  187.  
  188.     if(PhoneHandle->NumPhoneEntries + 1 > PhoneHandle->PhoneSize)
  189.     {
  190.         PhoneEntry    **LocalPhonebook;
  191.         LONG         LocalPhoneSize;
  192.  
  193.             /* Allocate another phone book table. */
  194.  
  195.         if(LocalPhonebook = CreatePhonebookTable(PhoneHandle->Phonebook,PhoneHandle->PhoneSize,PhoneHandle->PhoneSize + 1,&LocalPhoneSize))
  196.         {
  197.             FreeVecPooled(PhoneHandle->Phonebook);
  198.  
  199.             PhoneHandle->Phonebook = LocalPhonebook;
  200.             PhoneHandle->PhoneSize = LocalPhoneSize;
  201.         }
  202.         else
  203.             return(FALSE);
  204.     }
  205.  
  206.         /* Add it to the end of the table */
  207.  
  208.     PhoneHandle->Phonebook[PhoneHandle->NumPhoneEntries++] = NewEntry;
  209.  
  210.         /* And do the same for the list if any */
  211.  
  212.     if(PhoneHandle->PhoneList && NewEntry->Node)
  213.         AddTail(PhoneHandle->PhoneList,(struct Node *)NewEntry->Node);
  214.  
  215.     return(TRUE);
  216. }
  217.  
  218. BOOL
  219. MergePhonebooks(PhonebookHandle *SrcHandle,PhonebookHandle *DstHandle)
  220. {
  221.     PhoneEntry    **LocalPhonebook;
  222.     LONG         LocalPhoneSize;
  223.  
  224.         /* Create new table to hold the entries of both phonebooks */
  225.  
  226.     if(LocalPhonebook = CreatePhonebookTable(DstHandle->Phonebook,DstHandle->NumPhoneEntries,DstHandle->NumPhoneEntries + SrcHandle->NumPhoneEntries,&LocalPhoneSize))
  227.     {
  228.         LONG i,Count;
  229.  
  230.             /* Move the phonebook entries from the old phonebook to the other */
  231.  
  232.         for(i = 0, Count = DstHandle->NumPhoneEntries ; i < SrcHandle->NumPhoneEntries ; i++)
  233.         {
  234.             LocalPhonebook[Count] = SrcHandle->Phonebook[i];
  235.  
  236.             if(SrcHandle->Phonebook[i]->GroupNode)
  237.                 FreeVecPooled(SrcHandle->Phonebook[i]->GroupNode);
  238.  
  239.             SrcHandle->Phonebook[i]->GroupNode = NULL;
  240.             SrcHandle->Phonebook[i]->ThisGroup = NULL;
  241.  
  242.             AddTail(DstHandle->PhoneList,(struct Node *)SrcHandle->Phonebook[i]->Node);
  243.  
  244.             LocalPhonebook[Count]->Header->ID = DstHandle->PhonebookID++;
  245.  
  246.             Count++;
  247.         }
  248.  
  249.             /* Clear the rest */
  250.  
  251.         FreeList((struct List *)&SrcHandle->PhoneGroupList);
  252.         SrcHandle->NumPhoneEntries = 0;
  253.  
  254.             /* Put the new table into the destination phonebook */
  255.  
  256.         FreeVecPooled(DstHandle->Phonebook);
  257.  
  258.         DstHandle->Phonebook        = LocalPhonebook;
  259.         DstHandle->PhoneSize        = LocalPhoneSize;
  260.         DstHandle->NumPhoneEntries    = Count;
  261.  
  262.         return(TRUE);
  263.     }
  264.     else
  265.         return(FALSE);
  266. }
  267.  
  268. PhonebookHandle *
  269. CreatePhonebook(LONG NumEntries,BOOL AllocateEntries)
  270. {
  271.     PhonebookHandle *PhoneHandle;
  272.  
  273.         /* Create the header */
  274.  
  275.     if(PhoneHandle = (PhonebookHandle *)AllocVecPooled(sizeof(PhonebookHandle),MEMF_ANY|MEMF_CLEAR))
  276.     {
  277.             /* Create the table */
  278.  
  279.         if(PhoneHandle->Phonebook = CreatePhonebookTable(NULL,0,NumEntries,&PhoneHandle->PhoneSize))
  280.         {
  281.             PhoneEntry **Phonebook = PhoneHandle->Phonebook;
  282.             struct timeval Now;
  283.             LONG i;
  284.  
  285.                 /* Set up the ID counter */
  286.  
  287.             GetSysTime(&Now);
  288.             PhoneHandle->PhonebookID = Now.tv_secs;
  289.  
  290.                 /* Create the phonebook entries one by one */
  291.  
  292.             if(AllocateEntries)
  293.             {
  294.                 for(i = 0 ; i < NumEntries ; i++)
  295.                 {
  296.                     if(!(Phonebook[i] = CreatePhoneEntry(PhoneHandle)))
  297.                     {
  298.                         LONG j;
  299.  
  300.                         for(j = 0 ; j < i ; j++)
  301.                             DeletePhoneEntry(Phonebook[j]);
  302.  
  303.                         FreeVecPooled(Phonebook);
  304.                         FreeVecPooled(PhoneHandle);
  305.  
  306.                         return(NULL);
  307.                     }
  308.                 }
  309.             }
  310.  
  311.             PhoneHandle->NumPhoneEntries = NumEntries;
  312.  
  313.                 /* Initialize the lists */
  314.  
  315.             NewList((struct List *)&PhoneHandle->PhoneGroupList);
  316.  
  317.                 /* And the access semaphore */
  318.  
  319.             InitSemaphore(&PhoneHandle->ActiveSemaphore);
  320.  
  321.             return(PhoneHandle);
  322.         }
  323.  
  324.         FreeVecPooled(PhoneHandle);
  325.     }
  326.  
  327.     return(NULL);
  328. }
  329.  
  330. VOID
  331. DeletePhonebook(PhonebookHandle *PhoneHandle)
  332. {
  333.     if(PhoneHandle)
  334.     {
  335.         PhoneEntry **Phonebook = PhoneHandle->Phonebook;
  336.         LONG i;
  337.  
  338.             /* Delete the groups */
  339.  
  340.         FreePhoneGroupList((struct List *)&PhoneHandle->PhoneGroupList);
  341.  
  342.             /* Delete the single entries */
  343.  
  344.         for(i = 0 ; i < PhoneHandle->NumPhoneEntries ; i++)
  345.             DeletePhoneEntry(Phonebook[i]);
  346.  
  347.             /* Free the display list */
  348.  
  349.         FreeVecPooled(PhoneHandle->PhoneList);
  350.  
  351.             /* Delete the dial list */
  352.  
  353.         DeleteList(PhoneHandle->DialList);
  354.  
  355.             /* Delete the table */
  356.  
  357.         FreeVecPooled(PhoneHandle->Phonebook);
  358.  
  359.             /* And delete the header */
  360.  
  361.         FreeVecPooled(PhoneHandle);
  362.     }
  363. }
  364.  
  365.     /* CopyPhoneHeader():
  366.      *
  367.      *    Copy a phone header from one place to another. Only copy
  368.      *    the `sensible' data, not the unique entries.
  369.      */
  370.  
  371. VOID
  372. CopyPhoneHeader(PhoneHeader *From,PhoneHeader *To)
  373. {
  374.     strcpy(To->Name,        From->Name);
  375.     strcpy(To->Number,        From->Number);
  376.     strcpy(To->Comment,        From->Comment);
  377.  
  378.     strcpy(To->UserName,    From->UserName);
  379.     strcpy(To->Password,    From->Password);
  380.  
  381.     To->QuickMenu    = From->QuickMenu;
  382.     To->NoRates        = From->NoRates;
  383.     To->AutoDial    = From->AutoDial;
  384. }
  385.  
  386. LONG
  387. MovePhoneEntry(PhonebookHandle *PhoneHandle,LONG Index,LONG How)
  388. {
  389.     PhoneEntry **Phonebook;
  390.     PhoneEntry *Entry;
  391.     LONG NewPosition;
  392.  
  393.     Phonebook = PhoneHandle->Phonebook;
  394.     Entry = Phonebook[Index];
  395.     NewPosition = Index;
  396.  
  397.     switch(How)
  398.     {
  399.         case MOVE_HEAD:
  400.  
  401.             if(Index > 0)
  402.             {
  403.                 LONG i;
  404.  
  405.                 for(i = Index ; i > 0 ; i--)
  406.                     Phonebook[i] = Phonebook[i - 1];
  407.  
  408.                 NewPosition = 0;
  409.             }
  410.  
  411.             break;
  412.  
  413.         case MOVE_PRED:
  414.  
  415.             if(Index > 0)
  416.             {
  417.                 NewPosition = Index - 1;
  418.  
  419.                 Phonebook[Index] = Phonebook[NewPosition];
  420.             }
  421.  
  422.             break;
  423.  
  424.         case MOVE_SUCC:
  425.  
  426.             if(Index < PhoneHandle->NumPhoneEntries - 1)
  427.             {
  428.                 NewPosition = Index + 1;
  429.  
  430.                 Phonebook[Index] = Phonebook[NewPosition];
  431.             }
  432.  
  433.             break;
  434.  
  435.         case MOVE_TAIL:
  436.  
  437.             if(Index < PhoneHandle->NumPhoneEntries - 1)
  438.             {
  439.                 LONG i;
  440.  
  441.                 NewPosition = PhoneHandle->NumPhoneEntries - 1;
  442.  
  443.                 for(i = Index ; i < NewPosition ; i++)
  444.                     Phonebook[i] = Phonebook[i + 1];
  445.             }
  446.  
  447.             break;
  448.     }
  449.  
  450.     if(NewPosition != Index)
  451.     {
  452.         Phonebook[NewPosition] = Entry;
  453.  
  454.         if(Phonebook[NewPosition]->Node)
  455.             MoveNode(PhoneHandle->PhoneList,(struct Node *)Phonebook[NewPosition]->Node,How);
  456.     }
  457.  
  458.     return(NewPosition);
  459. }
  460.  
  461. PhoneEntry *
  462. GetActiveEntry(PhonebookHandle *PhoneHandle)
  463. {
  464.     PhoneEntry *Entry;
  465.  
  466.     SafeObtainSemaphoreShared(&PhoneHandle->ActiveSemaphore);
  467.  
  468.     Entry = PhoneHandle->ActiveEntry;
  469.  
  470.     ReleaseSemaphore(&PhoneHandle->ActiveSemaphore);
  471.  
  472.     return(Entry);
  473. }
  474.  
  475. VOID
  476. SetActiveEntry(PhonebookHandle *PhoneHandle,PhoneEntry *Entry)
  477. {
  478.     ObtainSemaphore(&PhoneHandle->ActiveSemaphore);
  479.  
  480.     PhoneHandle->ActiveEntry = Entry;
  481.  
  482.     ReleaseSemaphore(&PhoneHandle->ActiveSemaphore);
  483. }
  484.  
  485. PhoneEntry *
  486. LockActiveEntry(PhonebookHandle *PhoneHandle)
  487. {
  488.     SafeObtainSemaphoreShared(&PhoneHandle->ActiveSemaphore);
  489.  
  490.     return(PhoneHandle->ActiveEntry);
  491. }
  492.  
  493. VOID
  494. UnlockActiveEntry(PhonebookHandle *PhoneHandle)
  495. {
  496.     ReleaseSemaphore(&PhoneHandle->ActiveSemaphore);
  497. }
  498.  
  499. PhoneEntry *
  500. ClonePhoneEntry(PhonebookHandle *PhoneHandle,PhoneEntry *Source)
  501. {
  502.     PhoneEntry *Destination;
  503.  
  504.     if(Destination = CreatePhoneEntry(PhoneHandle))
  505.     {
  506.             /* Copy the header information */
  507.  
  508.         CopyPhoneHeader(Source->Header,Destination->Header);
  509.  
  510.             /* Delete the rates and costs of the new entry */
  511.  
  512.         FreeTimeDateList((struct List *)&Destination->TimeDateList);
  513.  
  514.             /* And replace it with a copy of the source data */
  515.  
  516.         if(CopyTimeDateList((struct List *)&Source->TimeDateList,(struct List *)&Destination->TimeDateList,FALSE))
  517.         {
  518.             LONG i,Len1,Len2;
  519.             LONG Copies;
  520.             UBYTE TempName[80];
  521.             STRPTR BaseName;
  522.             BOOL GotIt = TRUE;
  523.  
  524.                 /* Allocate space for the config data. */
  525.  
  526.             for(i = PREF_SERIAL ; i <= PREF_FASTMACROFILENAME ; i++)
  527.             {
  528.                 if(!CreateConfigEntry(Destination->Config,i))
  529.                 {
  530.                     GotIt = FALSE;
  531.                     break;
  532.                 }
  533.             }
  534.  
  535.             if(GotIt)
  536.             {
  537.                 STRPTR Trailer = NULL;
  538.  
  539.                     /* Copy the data. */
  540.  
  541.                 SaveConfig(Source->Config,Destination->Config);
  542.  
  543.                     /* Build the "Copy <filler>of" template */
  544.  
  545.                 LimitedSPrintf(sizeof(TempName),TempName,LocaleString(MSG_COPY_OF_TXT)," <filler>");
  546.  
  547.                     /* Now look where the "<filler>" ended up */
  548.  
  549.                 for(i = 0 ; i < strlen(TempName) ; i++)
  550.                 {
  551.                     if(!Strnicmp(&TempName[i],"<filler>",strlen("<filler>")))
  552.                     {
  553.                             /* Chop off everything after the "Copy " string */
  554.  
  555.                         TempName[i] = 0;
  556.                         Trailer = &TempName[i + strlen("<filler>")];
  557.                         break;
  558.                     }
  559.                 }
  560.  
  561.                     /* Does this entry have a leading "Copy " string? */
  562.  
  563.                 if(!Strnicmp(TempName,Destination->Header->Name,strlen(TempName)))
  564.                 {
  565.                     BaseName = &Destination->Header->Name[strlen(TempName)];
  566.  
  567.                         /* Skip the numbers */
  568.  
  569.                     while(*BaseName >= '0' && *BaseName <= '9')
  570.                         BaseName++;
  571.  
  572.                         /* Skip the spaces */
  573.  
  574.                     while(*BaseName == ' ')
  575.                         BaseName++;
  576.  
  577.                         /* If there is the trailing "of", skip it */
  578.  
  579.                     if(!Strnicmp(BaseName,Trailer,strlen(Trailer)))
  580.                         BaseName += strlen(Trailer);
  581.  
  582.                         /* Skip the spaces */
  583.  
  584.                     while(*BaseName == ' ')
  585.                         BaseName++;
  586.                 }
  587.                 else
  588.                     BaseName = Destination->Header->Name;
  589.  
  590.                 Len1 = strlen(BaseName);
  591.  
  592.                 Copies = 0;
  593.  
  594.                 for(i = 0 ; i < PhoneHandle->NumPhoneEntries ; i++)
  595.                 {
  596.                     if(PhoneHandle->Phonebook[i] != Destination)
  597.                     {
  598.                         Len2 = strlen(PhoneHandle->Phonebook[i]->Header->Name);
  599.  
  600.                         if(Len2 >= Len1)
  601.                         {
  602.                             if(!Stricmp(&PhoneHandle->Phonebook[i]->Header->Name[Len2 - Len1],BaseName))
  603.                                 Copies++;
  604.                         }
  605.                     }
  606.                 }
  607.  
  608.                 if(Copies)
  609.                 {
  610.                     UBYTE Counter[10];
  611.  
  612.                     if(Copies > 1)
  613.                         LimitedSPrintf(sizeof(Counter),Counter," %ld ",Copies);
  614.                     else
  615.                         strcpy(Counter," ");
  616.  
  617.                     LimitedSPrintf(sizeof(TempName),TempName,LocaleString(MSG_COPY_OF_TXT),Counter);
  618.                     LimitedStrcat(sizeof(TempName),TempName," ");
  619.  
  620.                     if(strlen(TempName) + strlen(BaseName) < sizeof(Destination->Header->Name))
  621.                     {
  622.                         strcat(TempName,BaseName);
  623.  
  624.                         strcpy(Destination->Header->Name,TempName);
  625.                     }
  626.                 }
  627.  
  628.                 if(Destination->Node)
  629.                     LimitedSPrintf(sizeof(Destination->Node->LocalName),Destination->Node->LocalName,"      %s",Destination->Header->Name);
  630.  
  631.                 return(Destination);
  632.             }
  633.         }
  634.  
  635.         DeletePhoneEntry(Destination);
  636.     }
  637.  
  638.     return(NULL);
  639. }
  640.